home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / less / charset.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-04  |  3.5 KB  |  206 lines

  1. /*
  2.  * Functions to define the character set
  3.  * and do things specific to the character set.
  4.  */
  5.  
  6. #include "less.h"
  7.  
  8. /*
  9.  * Predefined character sets,
  10.  * selected by the LESSCHARSET environment variable.
  11.  */
  12. struct charset {
  13.     char *name;
  14.     char *desc;
  15. } charsets[] = {
  16.     { "ascii",    "8bcccbcc18b95.b"    },
  17.     { "latin1",    "8bcccbcc18b95.33b."    },
  18.     { NULL }
  19. };
  20.  
  21. #define    IS_BINARY_CHAR    01
  22. #define    IS_CONTROL_CHAR    02
  23.  
  24. static char chardef[256];
  25. static char *binfmt = "\\%o";
  26. public int binattr = BLINK;
  27.  
  28. extern char *getenv();
  29.  
  30. /*
  31.  * Define a charset, given a description string.
  32.  * The string consists of 256 letters,
  33.  * one for each character in the charset.
  34.  * If the string is shorter than 256 letters, missing letters
  35.  * are taken to be identical to the last one.
  36.  * A decimal number followed by a letter is taken to be a 
  37.  * repetition of the letter.
  38.  *
  39.  * Each letter is one of:
  40.  *    . normal character
  41.  *    b binary character
  42.  *    c control character
  43.  */
  44.     static void
  45. ichardef(s)
  46.     char *s;
  47. {
  48.     register char *cp;
  49.     register int n;
  50.     register char v;
  51.  
  52.     n = 0;
  53.     cp = chardef;
  54.     while (*s != '\0')
  55.     {
  56.         switch (*s++)
  57.         {
  58.         case '.':
  59.             v = 0;
  60.             break;
  61.         case 'c':
  62.             v = IS_CONTROL_CHAR;
  63.             break;
  64.         case 'b':
  65.             v = IS_BINARY_CHAR|IS_CONTROL_CHAR;
  66.             break;
  67.  
  68.         case '0': case '1': case '2': case '3': case '4':
  69.         case '5': case '6': case '7': case '8': case '9':
  70.             n = (10 * n) + (s[-1] - '0');
  71.             continue;
  72.  
  73.         default:
  74.             error("invalid chardef", NULL_PARG);
  75.             quit(1);
  76.             /*NOTREACHED*/
  77.         }
  78.  
  79.         do
  80.         {
  81.             if (cp >= chardef + sizeof(chardef))
  82.             {
  83.                 error("chardef longer than 256", NULL_PARG);
  84.                 quit(1);
  85.                 /*NOTREACHED*/
  86.             }
  87.             *cp++ = v;
  88.         } while (--n > 0);
  89.         n = 0;
  90.     }
  91.  
  92.     while (cp < chardef + sizeof(chardef))
  93.         *cp++ = v;
  94. }
  95.  
  96. /*
  97.  * Define a charset, given a charset name.
  98.  * The valid charset names are listed in the "charsets" array.
  99.  */
  100.     static int
  101. icharset(name)
  102.     register char *name;
  103. {
  104.     register struct charset *p;
  105.  
  106.     if (name == NULL || *name == '\0')
  107.         return (0);
  108.  
  109.     for (p = charsets;  p->name != NULL;  p++)
  110.     {
  111.         if (strcmp(name, p->name) == 0)
  112.         {
  113.             ichardef(p->desc);
  114.             return (1);
  115.         }
  116.     }
  117.  
  118.     error("invalid charset name", NULL_PARG);
  119.     quit(1);
  120.     /*NOTREACHED*/
  121. }
  122.  
  123. /*
  124.  * Initialize charset data structures.
  125.  */
  126.     public void
  127. init_charset()
  128. {
  129.     register char *s;
  130.  
  131.     /*
  132.      * Try environment variable LESSCHARSET.
  133.      * If LESSCHARSET is not set, try LESSCHARDEF.
  134.      * If LESSCHARDEF is not set, default to "ascii" charset.
  135.      */
  136.     s = getenv("LESSCHARSET");
  137.     if (icharset(s))
  138.         return;
  139.  
  140.     s = getenv("LESSCHARDEF");
  141.     if (s != NULL && *s != '\0')
  142.     {
  143.         ichardef(s);
  144.         return;
  145.     }
  146.  
  147.     (void) icharset("ascii");
  148.  
  149.     s = getenv("LESSBINFMT");
  150.     if (s != NULL && *s != '\0')
  151.     {
  152.         if (*s == '*')
  153.         {
  154.             switch (s[1])
  155.             {
  156.             case 'd':  binattr = BOLD;      break;
  157.             case 'k':  binattr = BLINK;     break;
  158.             case 'u':  binattr = UNDERLINE; break;
  159.             default:   binattr = NORMAL;    break;
  160.             }
  161.             s += 2;
  162.         }
  163.         if (*s != '\0')
  164.             binfmt = s;
  165.     }
  166. }
  167.  
  168. /*
  169.  * Is a given character a "binary" character?
  170.  */
  171.     public int
  172. binary_char(c)
  173.     int c;
  174. {
  175.     return (chardef[c] & IS_BINARY_CHAR);
  176. }
  177.  
  178. /*
  179.  * Is a given character a "control" character?
  180.  */
  181.     public int
  182. control_char(c)
  183.     int c;
  184. {
  185.     return (chardef[c] & IS_CONTROL_CHAR);
  186. }
  187.  
  188. /*
  189.  * Return the printable form of a character.
  190.  * For example, in the "ascii" charset '\3' is printed as "^C".
  191.  */
  192.     public char *
  193. prchar(c)
  194.     int c;
  195. {
  196.     static char buf[8];
  197.  
  198.     if (!control_char(c))
  199.         sprintf(buf, "%c", c);
  200.     else if (!control_char(c ^ 0100))
  201.         sprintf(buf, "^%c", c ^ 0100);
  202.     else
  203.         sprintf(buf, binfmt, c);
  204.     return (buf);
  205. }
  206.